﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FCN
{
    public class poolxy
    {
        public int x,y,nx,ny;
        public float value;
    }
   public   class Matrix
    {
       public float[,] values = new float[0, 0];
        public float[,] upmaxxy = new float[0,0];
        public   List<poolxy> poolxies = new List<poolxy>();
        public Matrix()
        {
          
        }
        static   float sigmod(float x)
        {
            return (float) (1 / (1 + Math.Pow(Math.E, -x)));
        }
        public Matrix(int x,int y)
        {
            values = new float[x, y];
            float[,] maxxy = new float[x , y];
        }
        //public static float[,] uppooling(Matrix matrix,int scaleSize)
        //{

        //}
        public static float[,] DFull(float[,] matrix, float[,] kernel, int stride, int p)
        {
            int m = matrix.GetLength(0);
            int n = matrix.GetLength(1);
            int km = kernel.GetLength(0);
            int kn = kernel.GetLength(1);
            float[,] extendMatrix = new float[(m * stride) + (2 - p) * (km - 1), (n * stride) + (2 - p) * (kn - 1)];

            int s = 0, h = 0;
            for (int i = 0; i < m; i += stride)
            {

                h = 0;
                for (int j = 0; j < n; j += stride)
                {
                    int a = i + km - 1;
                    int b = j + kn - 1;
                    extendMatrix[i + km - 1, j + kn - 1] = matrix[s, h];
                    h++;
                }
                s++;
            }


            return extendMatrix;
        }
        public static float[,] convnFull(float[,] matrix, float[,] kernel,int stride,int p,bool puls=true)
        {
            int m = matrix.GetLength(0);
            int n = matrix.GetLength(1);
            int km = kernel.GetLength(0);
            int kn = kernel.GetLength(1);
            float[,] extendMatrix = new float[(m* stride) + (2-p) * (km - 1), (n* stride) + (2-p) * (kn - 1)];
            if (puls)
            {
                int s = 0,h=0;
                for (int i = 0; i < m; i+= stride)
                {
                   
                    h = 0;
                    for (int j = 0; j < n; j += stride)
                    {
                        int a = i + km - 1;
                        int b = j + kn - 1;
                        extendMatrix[i + km - 1, j + kn - 1] = matrix[s, h];
                        h++;
                    }
                    s++;
                }
            }
            else
                extendMatrix = matrix;


            return convnValid(extendMatrix, kernel,  1,p);
        }

        public static float[,] convnFCN(float[,] matrix, float[,] kernel, int stride, int p)
        {
            int m = matrix.GetLength(0);
            int n = matrix.GetLength(1);
            int km = kernel.GetLength(0);
            int kn = kernel.GetLength(1);
            float[,] extendMatrix = new float[(m * stride) + (2 - p) * (km - 1), (n * stride) + (2 - p) * (kn - 1)];
            int m2 = extendMatrix.GetLength(0);
            int n2 = extendMatrix.GetLength(1);
            int s = 0, h = 0;
                for (int i = 0; i < m2; i += stride)
                {

                    h = 0;
                    for (int j = 0; j < n2; j += stride)
                    {

                        extendMatrix[i, j ] = matrix[s, h];
                        h++;
                    }
                    s++;
                }
           


            return convnValid(extendMatrix, kernel, 1, p);
        }
        public static float[,] convnValid(float[,] matrix, float[,] kernel, int stride,int p)
        {
            //		kernel = rot180(kernel);
            //int m = matrix.GetLength(0);
            //int n = matrix.GetLength(1);
            //int km = kernel.GetLength(0);
            //int kn = kernel.GetLength(1);
            ////var row = ((x - x2) + 2 * p) / stride + 1;
            ////var col = ((y - y2) + 2 * p) / stride + 1;
            //int kns = ((n - kn) + 2 * p) / stride + 1;// n - kn + 1;
            //int kms = ((m - km) + 2 * p) / stride + 1;//m - km + 1;
            //float[,] outMatrix = new float[kms, kns];
          
            //for (int i = 0; i < kms; i++)
            //{
            //    for (int j = 0; j < kns; j++)
            //    {
            //        float sum = 0.0f;
            //        for (int ki = 0; ki < km; ki++)
            //        {
            //            for (int kj = 0; kj < kn; kj++)
            //                sum += matrix[i + ki, j + kj] * kernel[ki, kj];
            //        }
            //        outMatrix[i, j] = sum;

            //    }
            //}

            var x = matrix.GetLength(0);
            var y = matrix.GetLength(1);
            var x2 = kernel.GetLength(0);
            var y2 = kernel.GetLength(1);
           
            //Ho=(H−F+2×P)/S+1
            var row = ((x - x2) + 2 * p) / stride + 1;
            var col = ((y - y2) + 2 * p) / stride + 1;
            float[,] temp = new float[row, col];
            var nx = 0;

            for (var i = 0 - p; i <= x - x2 + p; i = i + stride)
            {
                var ny = 0;
                for (var j = 0 - p; j <= y - y2 + p; j = j + stride)
                {
                    if (temp.GetLength(0) > nx && temp.GetLength(1) > ny)
                        //var sum = 0.0f;
                        for (var i2 = 0; i2 < x2; i2++)
                            for (var j2 = 0; j2 < y2; j2++)
                            {
                                if (i + i2 < 0 || j + j2 < 0)
                                    temp[nx, ny] += 0;
                                else if (i + i2 >= x || j + j2 >= y)
                                    temp[nx, ny] += 0;
                                else
                                    temp[nx, ny] += matrix[i + i2, j + j2] * kernel[i2, j2];

                            }
                    //temp[nx, ny] = Math.Max(ReLU, temp[nx, ny] + bias);
                    ny++;
                }
                nx++;
            }

            return temp;
          //  return outMatrix;
        }

      public  static float[,] normalizedLog(float[,] values)
        {
            int m = values.GetLength(0);
            int n = values.GetLength(1);
            float[,] outMatrix = new float[m, n ];

            for (int i = 0; i < m; i++)
            {
                for (int j = 0; j < n; j++)
                {//atan(x) * 2 / π
                   // outMatrix[i, j] = (float)(Math.Atan(values[i, j])*2/Math.PI);
                    outMatrix[i,j] =(float)Math.Log10( values[i, j]);
                }
            }
            return outMatrix;
        }
        public static float[,] normalizedMinMax(float[,] values)
        {
            int m = values.GetLength(0);
            int n = values.GetLength(1);
            float[,] outMatrix = new float[m, n];
            float Min = float.MaxValue; float Max = float.MinValue;
            //x' = (x - X_min) / (X_max - X_min)
            for (int i = 0; i < m; i++)
            {
                for (int j = 0; j < n; j++)
                {//atan(x) * 2 / π
                    if (values[i, j] > Max)
                        Max = values[i, j];
                    if (values[i, j] <Min )
                        Min = values[i, j];

                    // outMatrix[i,j] =(float)Math.Log10( values[i, j]);
                }
            }
            for (int i = 0; i < m; i++)
            {
                for (int j = 0; j < n; j++)
                {//atan(x) * 2 / π
                    outMatrix[i, j] = (values[i, j] - Min) / (Max - Min);
                    // outMatrix[i,j] =(float)Math.Log10( values[i, j]);
                }
            }
            return outMatrix;
        }
      

        public static float[,] normalizedAtan(float[,] values)
        {
            int m = values.GetLength(0);
            int n = values.GetLength(1);
            float[,] outMatrix = new float[m, n];

            for (int i = 0; i < m; i++)
            {
                for (int j = 0; j < n; j++)
                {//atan(x) * 2 / π
                    outMatrix[i, j] = (float)(Math.Atan(values[i, j]) * 2 / Math.PI);
                    // outMatrix[i,j] =(float)Math.Log10( values[i, j]);
                }
            }
            return outMatrix;
        }
        public static Matrix MaxPooling(float[,] map, int stride)
        {
            Matrix ma = new Matrix();
            ma.values = map;
            return MaxPooling(ma, stride);
        }
        public static float[,] averPooling(float[,] matrix, int scale)
        {
            int m = matrix.GetLength(0);
            int n = matrix.GetLength(1);
             int sm = m / scale;
             int sn = n / scale;
             float[,] outMatrix = new float[sm,sn];
            if (sm * scale != m || sn * scale != n)
                throw new Exception("scale matrix");
             int size = scale * scale;
            for (int i = 0; i < sm; i++)
            {
                for (int j = 0; j < sn; j++)
                {
                    float sum = 0.0f;
                    for (int si = i * scale; si < (i + 1) * scale; si++)
                    {
                        for (int sj = j * scale; sj < (j + 1) * scale; sj++)
                        {
                            sum += matrix[si,sj];
                        }
                    }
                    outMatrix[i,j] = sum / size;
                }
            }
            return outMatrix;
        }
        public static Matrix MaxPooling(Matrix map, int stride)
        {
            Matrix pool = new Matrix();
            var i = map.values.GetLength(0);
            var j = map.values.GetLength(1);

            var rx = i;
            var ry = j;
            pool  = new Matrix(rx / stride, ry / stride);
            pool .upmaxxy = new float[rx, ry];
            int xx2 = 0;
            int yy2 = 0;
            for (i = 0; i < rx; i = i + stride)
            {

                if (pool .values.GetLength(0) > xx2)
                {
                    int tx = 0, ty = 0;
                    for (j = 0; j < ry; j = j + stride)
                    {
                        if (pool .values.GetLength(1) > yy2)
                        {
                            float max = 0.0f;
                            for (var xx = 0; xx < stride; xx++)
                                for (var yy = 0; yy < stride; yy++)
                                {
                                    if (map.values[i + xx, j + yy] > max)
                                    {
                                        tx = i + xx;
                                        ty = j + yy;
                                    }
                                    max = Math.Max(max, map.values[i + xx, j + yy]);

                                }

                            pool .values[xx2, yy2] = max;
                            pool .upmaxxy[tx, ty] = max;
                            poolxy pxy = new poolxy();
                            pxy.x = tx;
                            pxy.y = ty;
                            pxy.nx = xx2;
                            pxy.ny = yy2;
                            //     pxy.value = max;
                            pool .poolxies.Add(pxy);
                            yy2++;
                        }

                    }
                    //

                }
                yy2 = 0;
                xx2++;
            }
            return pool;
        }

        public static Matrix[,] MaxPooling(Matrix[,] map, int stride)
        {
            var row = map.GetLength(0);
            var col = map.GetLength(0);
            Matrix[,] pool = new Matrix[row, col];

            for (var x = 0; x < row; x++)
            {
                for (var y = 0; y < col; y++)
                {
                    var i = map[x, y].values.GetLength(0);
                    var j = map[x, y].values.GetLength(1);
                  
                    var rx = i;
                    var ry = j;
                    pool[x, y] = new Matrix(rx / stride, ry / stride);
                    pool[x, y].upmaxxy = new float[rx, ry];
                    int xx2 = 0;
                    int yy2 = 0;
                    for (i = 0; i < rx; i = i + stride)
                    {

                        if (pool[x, y].values.GetLength(0) > xx2)
                        {
                            int tx = 0, ty = 0;
                            for (j = 0; j < ry; j = j + stride)
                            {
                                if (pool[x, y].values.GetLength(1) > yy2)
                                {
                                    float max = 0.0f;
                                    for (var xx = 0; xx < stride; xx++)
                                        for (var yy = 0; yy < stride; yy++)
                                        {
                                            if (map[x, y].values[i + xx, j + yy] > max)
                                            {
                                                tx = i + xx;
                                                ty = j + yy;
                                            }
                                            max = Math.Max(max, map[x, y].values[i + xx, j + yy]);
                                            
                                        }

                                    pool[x, y].values[xx2, yy2] = max;
                                    pool[x, y].upmaxxy[tx, ty] = max;
                                    poolxy pxy = new poolxy();
                                    pxy.x = tx;
                                    pxy.y = ty;
                                    pxy.nx = xx2;
                                    pxy.ny = yy2;
                                    //     pxy.value = max;
                                    pool[x, y].poolxies.Add(pxy);
                                   yy2++;
                                }
                               
                            }
                            //

                        }
                        yy2 = 0;
                        xx2++;
                    }
                }
            }

            return pool;
        }
        public static float[,] kroneckerMax(float[,] matrix, int scale, List<poolxy> poolxiestemp)
        {
            int m = matrix.GetLength(0);
            int n = matrix.GetLength(1);
            float[,] outMatrix = new float[m * scale, n * scale];

            foreach (poolxy pxy in poolxiestemp)
            {
                outMatrix[pxy.x, pxy.y] = matrix[pxy.nx, pxy.ny];
            }
            return outMatrix;
        }
        public static float[,] kroneckerAvg(float[,] matrix, int scale)
        {
              int m = matrix.GetLength(0);
            int n = matrix.GetLength(1);
            float[,] outMatrix = new float[m * scale,n * scale];

            for (int i = 0; i < m; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    for (int ki = i * scale; ki < (i + 1) * scale; ki++)
                    {
                        for (int kj = j * scale; kj < (j + 1) * scale; kj++)
                        {
                            outMatrix[ki,kj] = matrix[i,j];
                        }
                    }
                }
            }
            return outMatrix;
        }
        public static Matrix gradient(Matrix ma, Matrix mb,float RELU)
        { 
            //float output_value = layer_neuron_act_[output_layer][d];
          //// gradient 
          //// = delta E / delta w 
          //// = (y0 - y0,target) * (delta f(x) / delta sigma(x) = getRELUGradFromY)
          //layer_neuron_grad_[output_layer][d] = (target[d] - output_value) * getRELUGradFromY(output_value);

            int m = ma.values.GetLength(0);
            int n = ma.values.GetLength(1);
            Matrix mc = new Matrix(m, n);
            for (int i = 0; i < m; i++)
                for (int j = 0; j < n; j++) {
                    float output_value = mb.values[i, j];
                    mc.values[i, j] = (ma.values[i, j] - output_value) * getRELUGradFromY(output_value, RELU);
                }
                    return mc;
        }

       static float getRELUGradFromY(float x,float RELU)
        {
            if (x > RELU) return 1.0f;
            else return RELU;
        }
        static float getmax(float x, float RELU)
        {
            if (x > RELU) return RELU;
            else return x;
        }
        public  static float[,] MatrixMAX(float[,] matrix, float max)
        {
            var x = matrix.GetLength(0);
            var y = matrix.GetLength(1);
            float[,] m = new float[x, y];
            for (var i = 0; i < x; i++)
                for (var j = 0; j < y; j++)
                    m[i, j] = getmax(matrix[i, j], max);
            return m;
        }
        public static float[,] Clone(float[,] matrix)
        {
            var x = matrix.GetLength(0);
            var y = matrix.GetLength(1);
            float[,] m = new float[x,y];
            for (var i = 0; i < x; i++)
                for (var j = 0; j < y; j++)
                    m[i, j] = matrix[i, j];
            return m;
        }
        public static float[,] rot180(float[,] matrix)
        {
            float[,] ma = Clone(matrix);
            int m = ma.GetLength(0);
            int n = ma.GetLength(1);
            for (int i = 0; i < m; i++)
            {
                for (int j = 0; j < n / 2; j++)
                {
                    float tmp = ma[i,j];
                    ma[i,j] = ma[i,n - 1 - j];
                    ma[i,n - 1 - j] = tmp;
                }
            }
            for (int j = 0; j < n; j++)
            {
                for (int i = 0; i < m / 2; i++)
                {
                    float tmp = ma[i,j];
                    ma[i,j] = ma[m - 1 - i,j];
                    ma[m - 1 - i,j] = tmp;
                }
            }
            return ma;
        }
        public static Matrix MatrixMax(float[,] Ma, float[,] Mb)
        {
            int m = Ma.GetLength(0);
            int n = Ma.GetLength(1);
            int m2 = Mb.GetLength(0);
            int n2 = Mb.GetLength(1);

            if ((m != m2) || (n != n2))
            {
                Exception myException = new Exception("数组维数不匹配");
                throw myException;
            }

            Matrix Mc = new Matrix(m, n);
            float[,] c = Mc.values;
            float[,] a = Ma;
            float[,] b = Mb;

            for (int i = 0; i < m; i++)
                for (int j = 0; j < n; j++)
                    c[i, j] =Math.Max( a[i, j] ,b[i, j]) ;
            return Mc;
        }
        public static Matrix MatrixAdd(float[,] Ma, float[,] Mb,float bias=0)
        {
            int m = Ma.GetLength(0);
            int n = Ma.GetLength(1);
            int m2 = Mb.GetLength(0);
            int n2 = Mb.GetLength(1);

            if ((m != m2) || (n != n2))
            {
                Exception myException = new Exception("数组维数不匹配");
                throw myException;
            }

            Matrix Mc = new Matrix(m, n);
            float[,] c = Mc.values;
            float[,] a = Ma;
            float[,] b = Mb;

            for (int i = 0; i < m; i++)
                for (int j = 0; j < n; j++)
                    c[i, j] = a[i, j] + b[i, j]+ bias;
            return Mc;
        }
        
       public static Matrix activation_ReLU(float[,] Ma, float bias = 0,float relu=0)
        {
            int m = Ma.GetLength(0);
            int n = Ma.GetLength(1);


            Matrix Mc = new Matrix(m, n);
            float[,] c = Mc.values;
            float[,] a = Ma;


            for (int i = 0; i < m; i++)
                for (int j = 0; j < n; j++)
                    c[i, j] = Math.Max(a[i, j] + bias, relu);
            return Mc;
        }
        public static Matrix activation_Sigma(float[,] Ma, float bias = 0)
        {
            int m = Ma.GetLength(0);
            int n = Ma.GetLength(1);
          

            Matrix Mc = new Matrix(m, n);
            float[,] c = Mc.values;
            float[,] a = Ma;
        

            for (int i = 0; i < m; i++)
                for (int j = 0; j < n; j++)
                    c[i, j] = sigmod(a[i,j] + bias);
            return Mc;
        }
        public static float[,] divide(float[,] a, float b)
        {
            int hang = a.GetLength(0);
            int lie = a.GetLength(1);
            float[,] result = new float[hang, lie];
            for (int i = 0; i < hang; i++)
            {
                for (int j = 0; j < lie; j++)
                {
                    result[i, j] = a[i, j] / b;
                }
            }
            return result;
        }
            public Matrix Clone()
        {
            var x = values.GetLength(0);
            var y = values.GetLength(1);
            Matrix m = new Matrix(x,y);
            for (var i = 0; i < x; i++)
                for (var j = 0; j < y; j++)
                    m.values[i, j] = values[i, j];
            return m;
        }

        public void randinit()
        {
            var x = values.GetLength(0);
            var y = values.GetLength(1);
            Random rand = new Random();
            for (var i = 0; i < x; i++)
                for (var j = 0; j < y; j++)
                {
                    //System.Threading.Thread.Sleep(1);
                    values[i, j] = ((float)rand.Next() / Int32.MaxValue) * 0.1f;
                }
        }
        public Matrix convolution(Matrix m,int stride,float ReLU)
        {
            Matrix ma = new Matrix();
           
            ma.values = convolution(m.values, stride, ReLU,0);
            return ma;
        }

        public Matrix convolution(Matrix m, int stride, float ReLU,float bias)
        {
            Matrix ma = new Matrix();

            ma.values = convolution(m.values, stride, ReLU, bias);
            return ma;
        }
        public Matrix convolution(Matrix m, int stride, float ReLU, float bias,int p)
        {
            Matrix ma = new Matrix();

            ma.values = convolution(m.values, stride, ReLU, bias,p);
            return ma;
        }
        /// <summary>

        /// 矩阵乘法

        /// <param name="matrix1">矩阵1</param>

        /// <param name="matrix2">矩阵2</param>

        /// <returns>积</returns>

        public static  float[,] multiply(float[,] Ma, float[,] Mb)

        {

            int m = Ma.GetLength(0);
            int n = Ma.GetLength(1);
            int m2 = Mb.GetLength(0);
            int n2 = Mb.GetLength(1);

            if ((m != m2) || (n != n2))
            {
                Exception myException = new Exception("数组维数不匹配");
                throw myException;
            }

            Matrix Mc = new Matrix(m, n);
            float[,] c = Mc.values;


            for (int i = 0; i < m; i++)
                for (int j = 0; j < n; j++)
                {
                    float a = Ma[i, j];

                    float b =   Mb[i, j];
                    c[i, j] =(float)Math.Round( a * b,8);
                }
            return Mc.values;

        }

        public static float[,] multiply_lambda_alpha(float[,] Ma, float[,] Mb, float alpha, float LAMBDA)

        {
            int m = Ma.GetLength(0);
            int n = Ma.GetLength(1);
            int m2 = Mb.GetLength(0);
            int n2 = Mb.GetLength(1);

            if ((m != m2) || (n != n2))
            {
                Exception myException = new Exception("数组维数不匹配");
                throw myException;
            }

            Matrix Mc = new Matrix(m, n);
            float[,] c = Mc.values;
           

            for (int i = 0; i < m; i++)
                for (int j = 0; j < n; j++)
                {
                    float a = Ma[i, j];
                    a = a * (1 - LAMBDA * alpha);
                    float b = Mb[i, j] * alpha;
                    c[i, j] = a+ b;
                }
            return Mc.values;
            //matrix1是m*n矩阵，matrix2是n*p矩阵，则result是m*p矩阵

            

        }
        public static float[,] multiply_alpha(float[,] Ma, float[,] Mb, float alpha)

        {
            int m = Ma.GetLength(0);
            int n = Ma.GetLength(1);
            int m2 = Mb.GetLength(0);
            int n2 = Mb.GetLength(1);

            if ((m != m2) || (n != n2))
            {
                Exception myException = new Exception("数组维数不匹配");
                throw myException;
            }

            Matrix Mc = new Matrix(m, n);
            float[,] c = Mc.values;


            for (int i = 0; i < m; i++)
                for (int j = 0; j < n; j++)
                {
                    c[i, j] = Ma[i, j];
                    float delta_w = alpha * Ma[i, j] * Mb[i, j];
                     
                 //   a = a *  alpha;
                  
                    c[i, j]+= delta_w;
                }
            return Mc.values;
            //matrix1是m*n矩阵，matrix2是n*p矩阵，则result是m*p矩阵



        }
        public static float[,] onevalueAndmultiply(float[,] Ma, float[,] Mb)

        {
            int m = Ma.GetLength(0);
            int n = Ma.GetLength(1);
            int m2 = Mb.GetLength(0);
            int n2 = Mb.GetLength(1);

            if ((m != m2) || (n != n2))
            {
                Exception myException = new Exception("数组维数不匹配");
                throw myException;
            }

            Matrix Mc = new Matrix(m, n);
            float[,] c = Mc.values;


            for (int i = 0; i < m; i++)
                for (int j = 0; j < n; j++)
                {
                    float a = Ma[i, j];
                 
                    float b = 1 - Mb[i, j];
                    c[i, j] = a * b;
                }
            return Mc.values;
             
        }
        public float[,] convolution(float[,] m, int stride, int padding = 0)
        {

            var x = values.GetLength(0);
            var y = values.GetLength(1);
            var x2 = m.GetLength(0);
            var y2 = m.GetLength(1);
            var p = padding;
            //Ho=(H−F+2×P)/S+1
            var row = ((x - x2) + 2 * p) / stride + 1;
            var col = ((y - y2) + 2 * p) / stride + 1;
            float[,] temp = new float[row, col];
            var nx = 0;

            for (var i = 0 - p; i <= x - x2 + p; i = i + stride)
            {
                var ny = 0;
                for (var j = 0 - p; j <= y - y2 + p; j = j + stride)
                {
                    if (temp.GetLength(0) > nx && temp.GetLength(1) > ny)
                        //var sum = 0.0f;
                        for (var i2 = 0; i2 < x2; i2++)
                            for (var j2 = 0; j2 < y2; j2++)
                            {
                                if (i + i2 < 0 || j + j2 < 0)
                                    temp[nx, ny] += 0;
                                else if (i + i2 >= x || j + j2 >= y)
                                    temp[nx, ny] += 0;
                                else
                                    temp[nx, ny] += values[i + i2, j + j2] * m[i2, j2];

                            }
                   // temp[nx, ny] = Math.Max(ReLU, temp[nx, ny] + bias);
                    ny++;
                }
                nx++;
            }

            return temp;
        }
        public  float[,] convolution(float[,] m, int stride,float ReLU,float bias, int padding=0)
        {
            
            var x = values.GetLength(0);
            var y = values.GetLength(1);
            var x2 = m.GetLength(0);
            var y2 = m.GetLength(1);
            var p = padding;
            //Ho=(H−F+2×P)/S+1
            var row = ((x - x2)+2* p) / stride+1;
            var col = ((y - y2)+2* p) / stride+1;
            float[,] temp = new float[row, col];
            var nx = 0;
           
            for (var i = 0- p; i <= x-x2+ p; i = i + stride)
            {
                var  ny = 0;
                for (var j =0- p; j <= y-y2+ p; j = j + stride)
                {
                   if(temp.GetLength(0)> nx && temp.GetLength(1)> ny)
                    //var sum = 0.0f;
                    for (var i2 = 0; i2 < x2; i2++)
                        for (var j2 = 0; j2 < y2; j2++)
                        {
                                if (i + i2 < 0 || j + j2 < 0)
                                    temp[nx, ny] += 0;
                                else if (i + i2 >= x || j + j2 >= y)
                                    temp[nx, ny] += 0;
                                else
                                  temp[nx, ny] += values[i + i2, j + j2] * m[i2, j2];

                        }
                    temp[nx, ny] = Math.Max(ReLU, temp[nx, ny]+ bias);
                    ny++;
                }
                nx++;
            }
        
            return temp;
        }
        public float[,] convolutionsigmod(float[,] m, int stride, float bias, int padding = 0)
        {

            var x = values.GetLength(0);
            var y = values.GetLength(1);
            var x2 = m.GetLength(0);
            var y2 = m.GetLength(1);
            var p = padding;
            //Ho=(H−F+2×P)/S+1
            var row = ((x - x2) + 2 * p) / stride + 1;
            var col = ((y - y2) + 2 * p) / stride + 1;
            float[,] temp = new float[row, col];
            var nx = 0;

            for (var i = 0 - p; i <= x - x2 + p; i = i + stride)
            {
                var ny = 0;
                for (var j = 0 - p; j <= y - y2 + p; j = j + stride)
                {
                    if (temp.GetLength(0) > nx && temp.GetLength(1) > ny)
                        //var sum = 0.0f;
                        for (var i2 = 0; i2 < x2; i2++)
                            for (var j2 = 0; j2 < y2; j2++)
                            {
                                if (i + i2 < 0 || j + j2 < 0)
                                    temp[nx, ny] += 0;
                                else if (i + i2 >= x || j + j2 >= y)
                                    temp[nx, ny] += 0;
                                else
                                    temp[nx, ny] += values[i + i2, j + j2] * m[i2, j2];

                            }
                //    if(temp[nx, ny]!=0)
                    temp[nx, ny] =(float)Math.Round( sigmod( temp[nx, ny] + bias),8);
                    ny++;
                }
                nx++;
            }

            return temp;
        }

    }
}
